
import Singleton from "../Base/Singleton";
import { ApiMsgEnum, IApiPlayerJoinReq } from "../Common";
import { Connection } from "../Core";
import { Player } from "./Player";
import { RoomManager } from "./RoomManager";
/**
 * 管理所有player
 */
export class PlayerManager extends Singleton {
    static get Instance() {
        return super.GetInstance<PlayerManager>();
    }

    nextPlayerId  =1
    //set和map的时间复杂度是o(1)，如果用数组来存，遍历数组时的时间复杂度是o(n)，这里属于用空间换时间
    //并且set集合会自动去重，所以可以防止player被重复推进集合
    players:Set<Player> = new Set()
    idMapPlayer:Map<number,Player> = new Map()

    createPlayer({nickname,connection}:IApiPlayerJoinReq&{connection:Connection}){
        //每次创建一个player就让nextPlayerId++
        const player = new Player({id:this.nextPlayerId++,nickname,connection})
        this.players.add(player)
        this.idMapPlayer.set(player.id,player)
        return player
    }

    removePlayer(pid:number){
        const player = this.idMapPlayer.get(pid)
        if(player){
            //断开连接的时候判断玩家在不在房间里，不在则执行离开房间逻辑
            const rid = player.rid
            if(rid){
                RoomManager.Instance.leaveRoom(rid,player.id)
                // PlayerManager.Instance.syncPlayers() 入口文件中有同步，这里就不用同步了
                RoomManager.Instance.syncRooms()
                RoomManager.Instance.syncRoom(rid)
            }

            this.players.delete(player)
            this.idMapPlayer.delete(player.id)
        }
    }

    getPlayer(pid:number){
        return this.idMapPlayer.get(pid)
    }
    /**
     * 前端不需要player的connection属性，所以只传其他三个属性
     */
    getPlayerView({id,nickname,rid}:Player){
        return{
            id,nickname,rid
        }
    }
    /**
     * 获取所有玩家
     * 返回id，昵称，rid
     */
    getPlayersView(players:Set<Player> = this.players){
        return [...players].map((p)=>this.getPlayerView(p))
    }
    /**
     * 给已经存在的玩家同步其他玩家的登录信息
     */
    syncPlayers(){
        for (const player of this.players) {
            player.connection.sendMsg(ApiMsgEnum.MsgPlayerList,{
                list:this.getPlayersView()    
            })
        }
    }
}
